"use strict";
/*
*	Copyright (C) 1998-2018 by Northwoods Software Corporation. All Rights Reserved.
*/

/**
	This class implements an inspector for GoJS model data objects.
	The varructor takes three arguments:
	{string} divid a string referencing the HTML ID of the to-be inspector's div.
	{Diagram} diagram a reference to a GoJS Diagram.
	{Object} options An optional JS Object describing options for the inspector.

	Options:
		inspectSelection {boolean} Default true, whether to automatically show and populate the Inspector
		with the currently selected Diagram Part. If set to false, the inspector won't show anything
		until you call Inspector.inspectObject(object) with a Part or JavaScript object as the argument.
		includesOwnProperties {boolean} Default true, whether to list all properties currently on the inspected data object.
		properties {Object} An object of string:Object pairs representing propertyName:propertyOptions.
		Can be used to include or exclude additional properties.
		propertyModified function(propertyName, newValue) a callback
		multipleSelection {boolean} Default false, whether to allow multiple selection and change the properties of all the selected instead of
		the single first object
		showAllProperties {boolean} Default false, whether properties that are shown with multipleSelection use the intersect of the properties when false or the union when true
		only affects if multipleSelection is true
		showSize {number} Defaults 0, shows how many nodes are showed when selecting multiple nodes
		when its lower than 1, it shows all nodes

	Options for properties:
		show: {boolean|function} a boolean value to show or hide the property from the inspector, or a predicate function to show conditionally.
		readOnly: {boolean|function} whether or not the property is read-only
		type: {string} a string describing the data type. Supported values: "string|number|boolean|color|arrayofnumber|point|rect|size|spot|margin|select"
		defaultValue: {*} a default value for the property. Defaults to the empty string.
		choices: {Array|function} when type == "select", the Array of choices to use or a function that returns the Array of choices.

	Example usage of Inspector:

	var inspector = new Inspector("myInspector", myDiagram,
		{
			includesOwnProperties: false,
			properties: {
				"key": { show: Inspector.showIfPresent, readOnly: true },
				"comments": { show: Inspector.showIfNode	},
				"LinkComments": { show: Inspector.showIfLink },
				"chosen": { show: Inspector.showIfNode, type: "checkbox" },
				"state": { show: Inspector.showIfNode, type: "select", choices: ["Stopped", "Parked", "Moving"] }
			}
		});

	This is the basic HTML Structure that the Inspector creates within the given DIV element:

	<div id="divid" class="inspector">
		<tr>
			<td>propertyName</td>
			<td><input value=propertyValue /></td>
		</tr>
		...
	</div>
*/
function Inspector(divid, diagram, options) {
	var mainDiv = document.getElementById(divid);
	this._div = mainDiv;
	this._diagram = diagram;
	this._inspectedProperties = {};
	this._multipleProperties = {};

	// Either a GoJS Part or a simple data object, such as Model.modelData
	this.inspectedObject = null;

	// Inspector options defaults:
	this.includesOwnProperties = true;
	this.declaredProperties = {};
	this.inspectsSelection = true;
	this.propertyModified = null;
	this.multipleSelection = false;
	this.showAllProperties = false;
	this.showSize = 0;

	if (options !== undefined) {
		if (options["includesOwnProperties"] !== undefined) this.includesOwnProperties = options["includesOwnProperties"];
		if (options["properties"] !== undefined) this.declaredProperties = options["properties"];
		if (options["inspectSelection"] !== undefined) this.inspectsSelection = options["inspectSelection"];
		if (options["propertyModified"] !== undefined) this.propertyModified = options["propertyModified"];
		if (options['multipleSelection'] !== undefined) this.multipleSelection = options['multipleSelection'];
		if (options['showAllProperties'] !== undefined) this.showAllProperties = options['showAllProperties'];
		if (options['showSize'] !== undefined) this.showSize = options['showSize'];
	}

	var self = this;
	diagram.addModelChangedListener(function(e) {
		if (e.isTransactionFinished) self.inspectObject();
	});
	if (this.inspectsSelection) {
		diagram.addDiagramListener("ChangedSelection", function(e) { self.inspectObject(); });
	}
}

// Some static predicates to use with the "show" property.
Inspector.showIfNode = function(part) { return part instanceof go.Node };
Inspector.showIfLink = function(part) { return part instanceof go.Link };
Inspector.showIfGroup = function(part) { return part instanceof go.Group };

// Only show the property if its present. Useful for "key" which will be shown on Nodes and Groups, but normally not on Links
Inspector.showIfPresent = function(data, propname) {
	if (data instanceof go.Part) data = data.data;
	return typeof data === "object" && data[propname] !== undefined;
};

/**
* Update the HTML state of this Inspector given the properties of the {@link #inspectedObject}.
* @param {Object} object is an optional argument, used when {@link #inspectSelection} is false to
* set {@link #inspectedObject} and show and edit that object's properties.
*/
Inspector.prototype.inspectObject = function(object) {
	var inspectedObject = null;
	var inspectedObjects = null;
	if (object === null) return;
	if (object === undefined) {
		if (this.inspectsSelection) {
			if (this.multipleSelection) { // gets the selection if multiple selection is true
				inspectedObjects = this._diagram.selection;
			} else { // otherwise grab the first object
				inspectedObject = this._diagram.selection.first();
			}
		} else { // if there is a single inspected object
			inspectedObject = this.inspectedObject;
		}
	} else { // if object was passed in as a parameter
		inspectedObject = object;
	}
	if (inspectedObjects && inspectedObjects.count === 1) {
		inspectedObject = inspectedObjects.first();
	}
	if (inspectedObjects && inspectedObjects.count <= 1) {
		inspectedObjects = null;
	}

	// single object or no objects 单一对象或者无对象
	if (!inspectedObjects || !this.multipleSelection) {
		if (inspectedObject === null || this.inspectedObject === inspectedObject) {
			this.inspectedObject = inspectedObject;
			return;
		}

		this.inspectedObject = inspectedObject;
		if (this.inspectObject === null) return;
		var mainDiv = this._div;
		if(this._div != undefined) {
			mainDiv.innerHTML = '';
		}

		// use either the Part.data or the object itself (for model.modelData)
		var data = (inspectedObject instanceof go.Part) ? inspectedObject.data : inspectedObject;
		if (!data) return;
		
		if(this._div != undefined) {
			mainDiv.innerHTML = this.loadTable(data);
			this.addListen();
		}
		return;
	} else {
	}
};

/**
* 加载数据表格
*/
Inspector.prototype.loadTable = function(data) {
	var html = '<table>';
	
	if (data.category) {
		// 非连接线-开始、判断、执行、结束
		if (data.category == 'Start') {
			html += '<tr><td style="text-align: right;">名称：</td><td>开始</td></tr>';
			
		} else if (data.category == 'End') {
			html += '<tr><td style="text-align: right;">名称：</td><td>结束</td></tr>';
		} else if (data.category == 'Conditional') {
			html += '<tr><td style="text-align: right;">名称：</td><td>条件判断</td></tr>';
			html += '<tr><td style="text-align: right;">备注：</td><td><input data-type="ele-remark" value="' + (data.remark ? data.remark : '') + '" /></td></tr>';
			html += '<tr><td style="text-align: right;">判断条件：</td><td><input data-type="ele-cond" value="' + (data.cond ? data.cond : '') + '" /></td></tr>';
		} else if (data.category == 'Default') {
			html += '<tr><td style="text-align: right;">名称：</td><td>审批节点</td></tr>';
			html += '<tr><td style="text-align: right;">备注：</td><td><input data-type="ele-remark" value="' + (data.remark ? data.remark : '') + '" /></td></tr>';
			
			/*
				1.可按照运营机构的
				2.可按照组织机构的
				3.可按具体用户的
				4.可按角色的
				5.可并签可或签可转签
				6.可模块化
				7.可控制流转级别
			 */
			html += '<tr><td style="text-align: right;">审批员类型：</td><td>';
			html += '<input type="radio" style="width:20px;" data-type="ele-auditor-type" name="auditorType" value="1" ' + (data.auditorType && data.auditorType == 1 ? 'checked="true"' : '') + ' />运营机构上级</br>';
			html += '<input type="radio" style="width:20px;" data-type="ele-auditor-type" name="auditorType" value="2" ' + (data.auditorType && data.auditorType == 2 ? 'checked="true"' : '') + ' />组织机构上级</br>';
			html += '<input type="radio" style="width:20px;" data-type="ele-auditor-type" name="auditorType" value="3" ' + (data.auditorType && data.auditorType == 3 ? 'checked="true"' : '') + ' />指定用户</br>';
			html += '<input type="radio" style="width:20px;" data-type="ele-auditor-type" name="auditorType" value="4" ' + (data.auditorType && data.auditorType == 4 ? 'checked="true"' : '') + ' />指定角色并签</br>';
			html += '<input type="radio" style="width:20px;" data-type="ele-auditor-type" name="auditorType" value="5" ' + (data.auditorType && data.auditorType == 5 ? 'checked="true"' : '') + ' />指定角色或签</br>';
			html += '<input type="radio" style="width:20px;" data-type="ele-auditor-type" name="auditorType" value="6" ' + (data.auditorType && data.auditorType == 6 ? 'checked="true"' : '') + ' />指定脚本</br>';
			html += '<input type="radio" style="width:20px;" data-type="ele-auditor-type" name="auditorType" value="7" ' + (data.auditorType && data.auditorType == 7 ? 'checked="true"' : '') + ' />制单人</br>';
			html += '</td></tr>';
			html += '<tr><td style="text-align: right;">指定工号</td><td></td></tr>';
			html += '<tr><td style="text-align: right;">指定角色名</td><td><input data-type="ele-auditor-value" value="' + (data.auditorValue ? data.auditorValue : '') + '" /></td></tr>';
			html += '<tr><td style="text-align: right;">脚本</td><td></td></tr>';
		}
	} else {
		// 连接线
		if(data.from && data.to) {
			html += '<tr><td style="text-align: right;">名称：</td><td>连接线</td></tr>';
			if(data.visible) {
				html += '<tr><td style="text-align: right;">判断结果：</td><td><input type="radio" style="width:20px;" data-type="ele-cond-result" name="condResult" value="1" ' + (data.condResult && data.condResult == 1 ? 'checked="true"' : '') + ' />是</br><input type="radio" style="width:20px;" data-type="ele-cond-result" name="condResult" value="0" ' + (data.condResult && data.condResult == 0 ? 'checked="true"' : '') + ' />否</td></tr>';
			}
		}
	}
	html += '</table>';
	return html;
}

/**
* 添加数据监听
*/
Inspector.prototype.addListen = function() {

	var t = this;
	var data = this.inspectedObject.data;
	
    // 监听“名称输入框”
	$('#id_data_config').find('input[data-type="ele-text"]').on('change',function (e) {
        var v = $(this).val();
        t.updateProp('text', v);
    });
	
    // 监听“备注输入框”
	$('#id_data_config').find('input[data-type="ele-remark"]').on('change',function (e) {
        var v = $(this).val();
        t.updateProp('remark', v);
    });
	
    // 监听“类型输入框”
	$('#id_data_config').find('input[data-type="ele-type"]').on('change',function (e) {
        var v = $(this).val();
        t.updateProp('type', v);
    });
	
    // 监听“判断条件输入框”
	$('#id_data_config').find('input[data-type="ele-cond"]').on('change',function (e) {
        var v = $(this).val();
        t.updateProp('cond', v);
    });
	
    // 监听“判断结果单选框”
	$('#id_data_config').find('input[data-type="ele-cond-result"]').on('click',function (e) {
        var v = $(this).val();
        t.updateProp('condResult', v);
        t.updateProp('text', v == 1 ? '是' : '否');
    });
	
    // 监听“审批员类型单选框”
	$('#id_data_config').find('input[data-type="ele-auditor-type"]').on('click',function (e) {
        var v = $(this).val();
        t.updateProp('auditorType', v);
    });
	
    // 监听“指定值输入框”
	$('#id_data_config').find('input[data-type="ele-auditor-value"]').on('change',function (e) {
        var v = $(this).val();
        t.updateProp('auditorValue', v);
    });
	return;
}

/**
* 更新某个值
*/
Inspector.prototype.updateProp = function(propName, propValue) {
	var inspectedProps = this._inspectedProperties;
	var diagram = this._diagram;
	var isPart = this.inspectedObject instanceof go.Part;
	var data = isPart ? this.inspectedObject.data : this.inspectedObject;
	diagram.startTransaction('set all properties');
	diagram.model.setDataProperty(data, propName, propValue);
	diagram.commitTransaction('set all properties');
	if (this.propertyModified !== null) this.propertyModified(propName, propValue, this);
};
